import java.lang.*;
import java.io.*;
import java.util.*;
import org.apache.commons.collections.*;

public class Utilities 
{
	Tree root = null;
	
	public static HashSet<String> folderList = null;
	
	public static HashSet<String> dependecyExtenstionSet = null;
	public static HashSet<String> topExtenstionSet = null;
	static
	{
		dependecyExtenstionSet = new HashSet<String>();
		
		dependecyExtenstionSet.add("bin");
		dependecyExtenstionSet.add("timestamp");
		dependecyExtenstionSet.add("stamp");
		dependecyExtenstionSet.add("txt");
		dependecyExtenstionSet.add("ogg");
		dependecyExtenstionSet.add("o");
		dependecyExtenstionSet.add("h");
		dependecyExtenstionSet.add("so");
		dependecyExtenstionSet.add("0");
		dependecyExtenstionSet.add("class");
		dependecyExtenstionSet.add("jar");
		dependecyExtenstionSet.add("s");
		dependecyExtenstionSet.add("gen");
		
		topExtenstionSet = new HashSet<String>();
		
		topExtenstionSet.add("c");
		topExtenstionSet.add("cpp");
		topExtenstionSet.add("java");
		topExtenstionSet.add("d");
		topExtenstionSet.add("j");
		topExtenstionSet.add("p");
		topExtenstionSet.add("cc");
		topExtenstionSet.add("mk");
		topExtenstionSet.add("js");
	}
	
	Utilities()
	{
		root = new Tree();
		
		folderList = new HashSet<String>();
		folderList.add("abi");
		folderList.add("build");
		folderList.add("development");
		folderList.add("external");
		folderList.add("kernel");
		folderList.add("ndk");
		folderList.add("prebuilt");
		folderList.add("bionic");
		folderList.add("cts");
		folderList.add("device");
		folderList.add("frameworks");
		folderList.add("libcore");
		folderList.add("sdk");
		folderList.add("bootable");
		folderList.add("dalvik");
		folderList.add("docs");
		folderList.add("hardware");
		folderList.add("packages");
		folderList.add("system");
		folderList.add("prebuilt");
	}
	
	public static void addWhenNotEqual()
	{
		
	}
	
	public static void writeMapToFile(HashMap<String, String> map, String dstFile) 
		throws IOException
	{
		FileWriter fstream = new FileWriter(dstFile);
		BufferedWriter outBuffer = new BufferedWriter(fstream);
		
		Set<String> keySet = map.keySet();
		for (String key: keySet)
		{
			String value = map.get(key);
			
			outBuffer.write(key + ", " + value + "\n");
		}
		
		outBuffer.close();
	}
	
	public static void readMapFromFile(HashMap<String, String> map, String srcFile) 
		throws IOException
	{
		  FileInputStream fstream = new FileInputStream(srcFile);
		  // Get the object of DataInputStream
		  DataInputStream in = new DataInputStream(fstream);
		  BufferedReader inBuffer = new BufferedReader(new InputStreamReader(in));
		  
		  String line = null;
		  while((line = inBuffer.readLine()) != null)
		  {
			  String words[] = line.split(",");
			  
			  //System.out.println(words[0] + " : " + words[1]);
			  
			  map.put(words[0].trim(), words[1].trim());
		  }
	}
	
	public static void writeMultiMapToFile(MultiMap map, String dstFile) 
	throws IOException
	{
		FileWriter fstream = new FileWriter(dstFile);
		BufferedWriter outBuffer = new BufferedWriter(fstream);
		
		Set<String> keySet = map.keySet();
		for (String key: keySet)
		{
			Collection<String> valueCollection = (Collection<String>) map.get(key);
			
			Iterator it = valueCollection.iterator();
			while(it.hasNext())
			{
				outBuffer.write(key + ", " + it.next() + "\n");
			}
		}
		
		outBuffer.close();
	}
	
	public static void readMultiMapFromFile(MultiMap map, String srcFile) 
	throws IOException
	{
		  FileInputStream fstream = new FileInputStream(srcFile);
		  // Get the object of DataInputStream
		  DataInputStream in = new DataInputStream(fstream);
		  BufferedReader inBuffer = new BufferedReader(new InputStreamReader(in));
		  
		  String line = null;
		  while((line = inBuffer.readLine()) != null)
		  {
			  String words[] = line.split(",");
			  
			  //System.out.println(words[0] + " : " + words[1]);
			
			  map.put(words[0].trim(), words[1].trim());
		  }
	}
	
	public static void writeSetToFile(Set<String> set, String dstFile) 
			throws IOException
	{
		FileWriter fstream = new FileWriter(dstFile);
		BufferedWriter outBuffer = new BufferedWriter(fstream);
		
		for (String key: set)
		{	
			outBuffer.write(key + "\n");
		}
		
		outBuffer.close();
	}
	
	public static void readSetFromFile(Set<String> set, String srcFile) 
			throws IOException
	{
		  FileInputStream fstream = new FileInputStream(srcFile);
		  // Get the object of DataInputStream
		  DataInputStream in = new DataInputStream(fstream);
		  BufferedReader inBuffer = new BufferedReader(new InputStreamReader(in));
		  
		  String line = null;
		  while((line = inBuffer.readLine()) != null)
		  {			  
			  set.add(line.trim());
		  }
	}
	
	public static boolean isOutObj(String objName)
	{
		int indexOfUnderscore = objName.indexOf('_');
		if (indexOfUnderscore < 0)
		{
			return false;
		}
		
		int lastIndexOfUnderscore = objName.indexOf('_', indexOfUnderscore+1);
		if (lastIndexOfUnderscore < 0)
		{
			return false;
		}
		
		String firstName = objName.substring(indexOfUnderscore+1, lastIndexOfUnderscore);
		firstName = firstName.toLowerCase();
		if (firstName.equals("out") || firstName.equals("target") || firstName.equals("product"))
		{
			return true;
		}
		
		return false;
	}
	
	public static boolean isCtsbj(String objName)
	{
		int indexOfUnderscore = objName.indexOf('_');
		if (indexOfUnderscore < 0)
		{
			return false;
		}
		
		int lastIndexOfUnderscore = objName.indexOf('_', indexOfUnderscore+1);
		if (lastIndexOfUnderscore < 0)
		{
			return false;
		}
		
		String firstName = objName.substring(indexOfUnderscore+1, lastIndexOfUnderscore);
		firstName = firstName.toLowerCase();
		if (firstName.equals("cts"))
		{
			return true;
		}
		
		return false;
	}
	
	public boolean isLocalOBj(String objName)
	{
		if (queryTree(objName) == null)
		{
			return false;
		}
		
		return true;
	}
	
	public static String getExtension(String name)
	{
		int lastIndexOfUnderscore = name.lastIndexOf('_');
		
		return name.substring(lastIndexOfUnderscore + 1, name.length()).toLowerCase();
	}
	
	public static boolean isDependency(String name)
	{
		String extension = getExtension(name);
		
		if (dependecyExtenstionSet.contains(extension))
		{
			return true;
		}
		
		return false;
	}
	
	public static boolean isTop(String name)
	{
		String extension = getExtension(name);
		
		if (topExtenstionSet.contains(extension))
		{
			return true;
		}
		
		return false;
	}
	
	public static String truncat(int bypassNum, String src)
	{
		int beginIndex = 0;
		
		for (int i = 0; i < bypassNum; i++)
		{	
			beginIndex = src.indexOf('/', beginIndex) + 1;
			
			if ((beginIndex >= src.length()) || (beginIndex <= 0))
			{
				return null;
			}
		}
		
		return src.substring(beginIndex);
	}
	
	public static String getPath(String src)
	{
		int lastIndexOfSlash = src.lastIndexOf('/');
		
		if (lastIndexOfSlash < 0)
		{
			return null;
		}
		
		return src.substring(0, lastIndexOfSlash);
	}
	
	class Tree
	{
		String projName = null;
		String relativePath;
		ArrayList<Tree> kids = null;
		
		Tree()
		{
			kids = new ArrayList<Tree>();
		}
		
		private void insert(int beginIndex, String path, String projName)
		{
			
			//if we come down to the end of the path
			if (path.indexOf('/', beginIndex) < 0)
			{
				String relativePath = path.substring(beginIndex, path.length());
				
				Tree newKid = new Tree();
				kids.add(newKid);
				
				newKid.relativePath = relativePath;
				newKid.projName = projName;
				
				//System.out.println(relativePath);
				//System.out.println(projName);
				
				return;
			}
			
			String relativePath = path.substring(beginIndex, path.indexOf('/', beginIndex));
			//if such kid exists, go into it
			int i = 0;
			for (i = 0; i < kids.size(); i++)
			{
				if (kids.get(i).relativePath.equals(relativePath))
				{
					//System.out.print(relativePath + "\t");
					
					kids.get(i).insert(path.indexOf('/', beginIndex) + 1, path, projName);
					
					return;
				}
			}
			
			//if such kid does not exist, create one and go into it
			if (i == kids.size())
			{
				Tree newKid = new Tree();
				kids.add(newKid);
				
				newKid.relativePath = relativePath;
				
				//System.out.print(relativePath + "\t");
				
				newKid.insert(path.indexOf('/', beginIndex) + 1, path, projName);
			}
		}
		
		private String query(int beginIndex, String path)
		{		
			if (path == null)
			{
				return null;
			}
			
			//if we come down to the end of the path
			if (path.indexOf('/', beginIndex) < 0)
			{
				String relativePath = path.substring(beginIndex, path.length());
				
				int i = 0;
				for (i = 0; i < kids.size(); i++)
				{
					if (kids.get(i).relativePath.equals(relativePath))
					{
						//System.out.print(relativePath + "\t");
						
						return kids.get(i).projName;
					}
				}
				
				//if such kid does not exist, return null
				if (i == kids.size())
				{	
					return null;
				}
			}
			
			String relativePath = path.substring(beginIndex, path.indexOf('/', beginIndex));
			//if such kid exists, go into it
			int i = 0;
			for (i = 0; i < kids.size(); i++)
			{
				if (kids.get(i).relativePath.equals(relativePath))
				{
					//System.out.print(relativePath + "\t");
					
					if (kids.get(i).projName != null)
					{
						return kids.get(i).projName;
					}
					
					return kids.get(i).query(path.indexOf('/', beginIndex) + 1, path);
				}
			}
			
			//if such kid does not exist, return the projName
			if (i == kids.size())
			{	
				return this.projName;
			}
			
			return null;
		}
	}
	
	public void insertTree(String projPath, String projName)
	{
		root.insert(0, projPath, projName);
	}
	
	public String queryTree(String projPath)
	{
		return root.query(0, projPath);
	}
}
